package icasue.tools.sqlhelper.core;

import icasue.tools.sqlhelper.core.Queries;
import icasue.tools.sqlhelper.core.Limit;
import icasue.tools.sqlhelper.core.Sort;
import icasue.reflect.annotations.NotNull;
import icasue.reflect.annotations.Nullable;
import icasue.reflect.handles.predicate.SureOF;
import icasue.tools.sqlhelper.common.Const;

import java.util.LinkedList;
import java.util.List;
import java.util.function.Consumer;

/**
 * @Author: Qiao Hang
 * @CreateDate: 2021/10/14 下午3:26
 * @UpdateDate:
 * @Description:
 */
public class Consult<JavaType extends Object> {

    Class<JavaType> javaType;
    Queries _observe;

    List<Queries> queries;
    @Nullable
    String[] queryFields;
    @Nullable
    Limit limit;
    @Nullable
    Sort sort;

    /**
     * 该类定义常见的条件查询序列。
     */
    private Consult(@NotNull Class<JavaType> javaType){
        this.javaType = javaType;
        this.queries = new LinkedList<>();
    }

    // Builder.
    public static <Type> Consult<Type> build(Class<Type> javaType){
        return (Consult<Type>) new Consult(javaType);
    }

    // query fields mapping.
    public Consult<JavaType> queries(String... queryFields){
        SureOF.notNullAll(queryFields, "queries filed not be null.");
        this.queryFields = queryFields;
        return this;
    }

    // query limit.
    public Consult<JavaType> limit(Integer page,Integer size){
        this.limit = new Limit(page,size);
        return this;
    }

    // query sorts ASC.
    public Consult<JavaType> asc(String... ascFields){
        sort = new Sort(ascFields, Const.ASC);
        return this;
    }

    // query sorts DESC.
    public Consult<JavaType> desc(String... descFields){
        sort = new Sort(descFields, Const.DESC);
        return this;
    }

    private void seekNext(@NotNull String logic_relationship){
        if(_observe == null){
            logic_relationship = null;
        }
        _observe = new Queries(logic_relationship);
        queries.add(_observe);
    }

    public Consult<JavaType> where(){
        // PASS.
        return this;
    }

    // observe a queries group using 'AND'
    public Consult<JavaType> and(Consumer<Queries> nextQuery){
        seekNext(Const.AND);
        if(nextQuery != null)
            nextQuery.accept(_observe);
        return this;
    }

    // observe a queries group using 'OR'
    public Consult<JavaType> or(Consumer<Queries> nextQuery){
        seekNext(Const.OR);
        if(nextQuery != null)
            nextQuery.accept(_observe);
        return this;
    }

}
